typedef void EventCallback(arg);

class Bus {
  Bus._internal();

  static Bus _instance;

  static Bus get instance {
    if (_instance == null) {
      _instance = Bus._internal();
    }
    return _instance;
  }

  //保存事件订阅者队列，key:事件名(id)，value: 对应事件的订阅者队列
  var _eventMap = new Map<Object, List<EventCallback>>();

  //添加订阅者
  void on(eventName, EventCallback f) {
    if (eventName == null || f == null) return;
    _eventMap[eventName] ??= new List<EventCallback>();
    _eventMap[eventName].add(f);
  }

  // 移除订阅者
  // 不传第二个参数会移除所有订阅者
  void off(eventName, [EventCallback f]) {
    var list = _eventMap[eventName];
    if (eventName == null || list == null) return;
    if (f == null) {
      _eventMap[eventName] = null;
    } else {
      list.remove(f);
    }
  }

  // 触发事件，事件触发后该事件所有订阅者会被调用
  void emit(eventName, [arg]) {
    var list = _eventMap[eventName];
    if (list == null) return;
    int len = list.length - 1;
    // 反向遍历，防止订阅者在回调中移除自身带来的下标错位
    for (var i = len; i > -1; --i) {
      list[i](arg);
    }
  }
}
